-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--          http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
local Databases = require 'database'
local Col = require 'database.column'

local def_types = require 'class.types.types'

---@class PCIeDeviceTable: Table
---@field SlotID FieldBase
---@field Segment FieldBase
---@field SocketID FieldBase
---@field Bus FieldBase
---@field Device FieldBase
---@field Function FieldBase
---@field DevBus FieldBase
---@field DevDevice FieldBase
---@field DevFunction FieldBase
---@field DiagnosticFault FieldBase
---@field PredictiveFault FieldBase
---@field UCEByBIOS FieldBase
---@field BandwidthReduction FieldBase
---@field LinkSpeedReduced FieldBase
---@field FunctionClass FieldBase
---@field DeviceName FieldBase
---@field Position FieldBase
---@field FaultByBios FieldBase
---@field SlotType FieldBase
---@field FunctionProtocol FieldBase
---@field FunctionType FieldBase
---@field PCIeType FieldBase
---@field PCIeDeviceType FieldBase
---@field BaseClassCode FieldBase
---@field SubClassCode FieldBase
---@field ProgrammingInterface FieldBase
---@field MaxPCIeType FieldBase
---@field NegotiatedPCIeType FieldBase
---@field CorrectableError FieldBase
---@field UncorrectableError FieldBase
---@field FatalError FieldBase
---@field ParityError FieldBase
---@field SystemError FieldBase
---@field FatalErrorCount FieldBase
---@field NonFatalErrorCount FieldBase
---@field BadDLLPCount FieldBase
---@field BadTLPCount FieldBase
---@field UnsupportedRequestCount FieldBase
---@field CorrectableErrorOverfrequencyCount FieldBase
---@field TimeoutError FieldBase
---@field Container FieldBase
---@field DeviceType FieldBase
---@field RefComponent FieldBase
---@field GroupPosition FieldBase
---@field MultihostPresence FieldBase

---@class PCIeFunctionTable: Table
---@field SegmentNumber FieldBase
---@field BusNumber FieldBase
---@field DeviceNumber FieldBase
---@field FunctionNumber FieldBase
---@field RelatedProcessorId FieldBase
---@field RootBusNumber FieldBase
---@field RootDeviceNumber FieldBase
---@field RootFunctionNumber FieldBase
---@field VendorId FieldBase
---@field DeviceId FieldBase
---@field SubsystemVendorId FieldBase
---@field SubsystemId FieldBase
---@field FunctionProtocol FieldBase
---@field FunctionType FieldBase
---@field BaseClassCode FieldBase
---@field SubClassCode FieldBase
---@field ProgrammingInterface FieldBase
---@field FatalErrorCount FieldBase
---@field NonFatalErrorCount FieldBase
---@field BadDLLPCount FieldBase
---@field BadTLPCount FieldBase
---@field UnsupportedRequestCount FieldBase
---@field CorrectableErrorOverfrequencyCount FieldBase
---@field DeviceType FieldBase
---@field SlotId FieldBase
---@field BDF FieldBase

---@class PcieAddrInfoTable: Table
---@field GroupID FieldBase
---@field SlotID FieldBase
---@field ComponentType FieldBase
---@field ControllerIndex FieldBase
---@field ControllerType FieldBase
---@field SocketID FieldBase
---@field Segment FieldBase
---@field Bus FieldBase
---@field Device FieldBase
---@field Function FieldBase
---@field VendorID FieldBase
---@field DeviceID FieldBase
---@field PortID FieldBase
---@field Lanes FieldBase
---@field PCIeType FieldBase
---@field SlotType FieldBase
---@field ContainerUID FieldBase
---@field ContainerUnitType FieldBase
---@field Location FieldBase
---@field ContainerSlot FieldBase
---@field DevBus FieldBase
---@field DevDevice FieldBase
---@field DevFunction FieldBase
---@field GroupPosition FieldBase
---@field MultihostPresence FieldBase

---@class BDFConfigTable: Table
---@field SocketId FieldBase
---@field Type FieldBase
---@field ConfigLength FieldBase
---@field BDFConfigs FieldBase

---@class CpuBusInfoTable: Table
---@field SocketID FieldBase
---@field SysId FieldBase
---@field BusBaseAddr FieldBase
---@field BusSize FieldBase

---@class PCIeLoadInfoTable: Table
---@field Type FieldBase
---@field SlotID FieldBase
---@field ID FieldBase
---@field AuxID FieldBase
---@field Segment FieldBase
---@field SocketID FieldBase
---@field DevBus FieldBase
---@field DevDevice FieldBase
---@field DevFunction FieldBase
---@field MultihostPresence FieldBase

---@class PCIeCardFlashCheckerTable: Table
---@field GroupPosition FieldBase
---@field FaultStatus FieldBase
---@field PCIeQuadrupleList FieldBase

---@class PCIeCardDisplayCustomTable: Table
---@field QuadrupleId FieldBase
---@field CustomType FieldBase
---@field Enabled FieldBase
---@field CardType FieldBase

---@class Pcie_deviceDBDatabase
---@field db DataBase
---@field select fun(db:DataBase, table: any, ...): SelectStatement
---@field update fun(db:DataBase, table: any, ...): UpdateStatement
---@field insert fun(db:DataBase, table: any, ...): InsertStatement
---@field PCIeDevice PCIeDeviceTable
---@field PCIeFunction PCIeFunctionTable
---@field PcieAddrInfo PcieAddrInfoTable
---@field BDFConfig BDFConfigTable
---@field CpuBusInfo CpuBusInfoTable
---@field PCIeLoadInfo PCIeLoadInfoTable
---@field PCIeCardFlashChecker PCIeCardFlashCheckerTable
---@field PCIeCardDisplayCustom PCIeCardDisplayCustomTable
local Pcie_deviceDBDatabase = {}
Pcie_deviceDBDatabase.__index = Pcie_deviceDBDatabase

function Pcie_deviceDBDatabase.new(path, datas)
    local db = Databases(path)
    local obj = {db = db}

    obj.PCIeDevice = db:Table('t_pcie_dev_info', {
        SlotID = Col.IntegerField():cid(1):null():max_length(8),
        Segment = Col.IntegerField():cid(2):null():max_length(8),
        SocketID = Col.IntegerField():cid(3):null():max_length(8),
        Bus = Col.IntegerField():cid(4):null():max_length(8),
        Device = Col.IntegerField():cid(5):null():max_length(8),
        Function = Col.IntegerField():cid(6):null():max_length(8),
        DevBus = Col.IntegerField():cid(7):null():max_length(8),
        DevDevice = Col.IntegerField():cid(8):null():max_length(8),
        DevFunction = Col.IntegerField():cid(9):null():max_length(8),
        DiagnosticFault = Col.IntegerField():cid(10):persistence_key('protect_reset'):null():max_length(8),
        PredictiveFault = Col.IntegerField():cid(11):persistence_key('protect_reset'):null():max_length(8),
        UCEByBIOS = Col.IntegerField():cid(12):persistence_key('protect_reset'):null():max_length(8),
        BandwidthReduction = Col.IntegerField():cid(13):persistence_key('protect_reset'):null():max_length(8),
        LinkSpeedReduced = Col.IntegerField():cid(14):persistence_key('protect_reset'):null():max_length(8),
        FunctionClass = Col.IntegerField():cid(15):null():max_length(8),
        DeviceName = Col.TextField():cid(16):null(),
        Position = Col.TextField():cid(17):null(),
        FaultByBios = Col.IntegerField():cid(18):null():max_length(8),
        SlotType = Col.TextField():cid(19):null(),
        FunctionProtocol = Col.TextField():cid(20):null(),
        FunctionType = Col.TextField():cid(21):null(),
        PCIeType = Col.TextField():cid(22):null(),
        PCIeDeviceType = Col.TextField():cid(23):null(),
        BaseClassCode = Col.IntegerField():cid(24):persistence_key('protect_reset'):null():max_length(8),
        SubClassCode = Col.IntegerField():cid(25):persistence_key('protect_reset'):null():max_length(8),
        ProgrammingInterface = Col.IntegerField():cid(26):persistence_key('protect_reset'):null():max_length(8),
        MaxPCIeType = Col.TextField():cid(27):null(),
        NegotiatedPCIeType = Col.TextField():cid(28):null(),
        CorrectableError = Col.IntegerField():cid(29):persistence_key('protect_reset'):null():max_length(8),
        UncorrectableError = Col.IntegerField():cid(30):persistence_key('protect_reset'):null():max_length(8),
        FatalError = Col.IntegerField():cid(31):persistence_key('protect_reset'):null():max_length(8),
        ParityError = Col.IntegerField():cid(32):persistence_key('protect_reset'):null():max_length(8),
        SystemError = Col.IntegerField():cid(33):persistence_key('protect_reset'):null():max_length(8),
        FatalErrorCount = Col.IntegerField():cid(34):persistence_key('protect_reset'):null():max_length(32),
        NonFatalErrorCount = Col.IntegerField():cid(35):persistence_key('protect_reset'):null():max_length(32),
        BadDLLPCount = Col.IntegerField():cid(36):persistence_key('protect_reset'):null():max_length(32),
        BadTLPCount = Col.IntegerField():cid(37):persistence_key('protect_reset'):null():max_length(32),
        UnsupportedRequestCount = Col.IntegerField():cid(38):persistence_key('protect_reset'):null():max_length(32),
        CorrectableErrorOverfrequencyCount = Col.IntegerField():cid(39):persistence_key('protect_reset'):null()
            :max_length(32),
        TimeoutError = Col.IntegerField():cid(40):persistence_key('protect_reset'):null():max_length(8),
        Container = Col.TextField():cid(41):null(),
        DeviceType = Col.IntegerField():cid(42):null():max_length(8),
        RefComponent = Col.TextField():cid(43):null(),
        GroupPosition = Col.TextField():cid(44):primary_key(),
        MultihostPresence = Col.IntegerField():cid(45):null():max_length(32)
    }):create_if_not_exist(datas and datas['t_pcie_dev_info'])
    obj.PCIeFunction = db:Table('t_pcie_func_info', {
        SegmentNumber = Col.IntegerField():cid(1):null():max_length(16):default(65535),
        BusNumber = Col.IntegerField():cid(2):null():max_length(8):default(255),
        DeviceNumber = Col.IntegerField():cid(3):null():max_length(8):default(255),
        FunctionNumber = Col.IntegerField():cid(4):null():max_length(8):default(255),
        RelatedProcessorId = Col.IntegerField():cid(5):null():max_length(8):default(255),
        RootBusNumber = Col.IntegerField():cid(6):null():max_length(8):default(255),
        RootDeviceNumber = Col.IntegerField():cid(7):null():max_length(8):default(255),
        RootFunctionNumber = Col.IntegerField():cid(8):null():max_length(8):default(255),
        VendorId = Col.IntegerField():cid(9):null():max_length(16):default(65535),
        DeviceId = Col.IntegerField():cid(10):null():max_length(16):default(65535),
        SubsystemVendorId = Col.IntegerField():cid(11):null():max_length(16):default(65535),
        SubsystemId = Col.IntegerField():cid(12):null():max_length(16):default(65535),
        FunctionProtocol = Col.TextField():cid(13):null():default('\'PCIe\''),
        FunctionType = Col.TextField():cid(14):null():default('\'Physical\''),
        BaseClassCode = Col.IntegerField():cid(15):null():max_length(8):default(255),
        SubClassCode = Col.IntegerField():cid(16):null():max_length(8):default(255),
        ProgrammingInterface = Col.IntegerField():cid(17):null():max_length(8):default(255),
        FatalErrorCount = Col.IntegerField():cid(18):persistence_key('protect_reset'):null():max_length(32):default(0),
        NonFatalErrorCount = Col.IntegerField():cid(19):persistence_key('protect_reset'):null():max_length(32)
            :default(0),
        BadDLLPCount = Col.IntegerField():cid(20):persistence_key('protect_reset'):null():max_length(32):default(0),
        BadTLPCount = Col.IntegerField():cid(21):persistence_key('protect_reset'):null():max_length(32):default(0),
        UnsupportedRequestCount = Col.IntegerField():cid(22):persistence_key('protect_reset'):null():max_length(32)
            :default(0),
        CorrectableErrorOverfrequencyCount = Col.IntegerField():cid(23):persistence_key('protect_reset'):null()
            :max_length(32):default(0),
        DeviceType = Col.TextField():cid(24):primary_key():persistence_key('protect_reset'),
        SlotId = Col.IntegerField():cid(25):primary_key():persistence_key('protect_reset'):max_length(8),
        BDF = Col.TextField():cid(26):primary_key():persistence_key('protect_reset')
    }):create_if_not_exist(datas and datas['t_pcie_func_info'])
    obj.PcieAddrInfo = db:Table('t_pcie_addr_info', {
        GroupID = Col.IntegerField():cid(1):null():max_length(8),
        SlotID = Col.IntegerField():cid(2):null():max_length(8),
        ComponentType = Col.IntegerField():cid(3):null():max_length(8),
        ControllerIndex = Col.IntegerField():cid(4):null():max_length(8),
        ControllerType = Col.IntegerField():cid(5):null():max_length(8),
        SocketID = Col.IntegerField():cid(6):null():max_length(8),
        Segment = Col.IntegerField():cid(7):null():max_length(8),
        Bus = Col.IntegerField():cid(8):persistence_key('protect_reset'):null():max_length(8),
        Device = Col.IntegerField():cid(9):persistence_key('protect_reset'):null():max_length(8),
        Function = Col.IntegerField():cid(10):persistence_key('protect_reset'):null():max_length(8),
        VendorID = Col.IntegerField():cid(11):null():max_length(16),
        DeviceID = Col.IntegerField():cid(12):null():max_length(16),
        PortID = Col.IntegerField():cid(13):null():max_length(8):default(255),
        Lanes = Col.IntegerField():cid(14):null():max_length(8),
        PCIeType = Col.TextField():cid(15):null(),
        SlotType = Col.TextField():cid(16):null(),
        ContainerUID = Col.TextField():cid(17):null(),
        ContainerUnitType = Col.TextField():cid(18):null(),
        Location = Col.TextField():cid(19):null(),
        ContainerSlot = Col.IntegerField():cid(20):null():max_length(8),
        DevBus = Col.IntegerField():cid(21):null():max_length(8),
        DevDevice = Col.IntegerField():cid(22):null():max_length(8),
        DevFunction = Col.IntegerField():cid(23):null():max_length(8),
        GroupPosition = Col.TextField():cid(24):primary_key(),
        MultihostPresence = Col.IntegerField():cid(25):null():max_length(32)
    }):create_if_not_exist(datas and datas['t_pcie_addr_info'])
    obj.BDFConfig = db:Table('t_bdf_config', {
        SocketId = Col.IntegerField():cid(1):primary_key():max_length(8),
        Type = Col.TextField():cid(2):null(),
        ConfigLength = Col.IntegerField():cid(3):null():max_length(8):default(255),
        BDFConfigs = Col.JsonField():cid(4):null()
    }, 'protect_reset'):create_if_not_exist(datas and datas['t_bdf_config'])
    obj.CpuBusInfo = db:Table('t_cpu_bus_info', {
        SocketID = Col.IntegerField():cid(1):primary_key():max_length(8):default(0),
        SysId = Col.IntegerField():cid(2):null():max_length(8):default(1),
        BusBaseAddr = Col.IntegerField():cid(3):null():max_length(8):default(0),
        BusSize = Col.IntegerField():cid(4):null():max_length(8):default(0)
    }):create_if_not_exist(datas and datas['t_cpu_bus_info'])
    obj.PCIeLoadInfo = db:Table('t_pcie_load_info', {
        Type = Col.TextField():cid(1):primary_key():persistence_key('protect_reset'):default('\'NA\''),
        SlotID = Col.IntegerField():cid(2):primary_key():persistence_key('protect_reset'):max_length(8):default(0),
        ID = Col.IntegerField():cid(3):persistence_key('protect_reset'):null():max_length(32):default(0),
        AuxID = Col.IntegerField():cid(4):persistence_key('protect_reset'):null():max_length(32):default(0),
        Segment = Col.IntegerField():cid(5):persistence_key('protect_reset'):null():max_length(8):default(0),
        SocketID = Col.IntegerField():cid(6):persistence_key('protect_reset'):null():max_length(8):default(0),
        DevBus = Col.IntegerField():cid(7):persistence_key('protect_reset'):null():max_length(8):default(0),
        DevDevice = Col.IntegerField():cid(8):persistence_key('protect_reset'):null():max_length(8):default(0),
        DevFunction = Col.IntegerField():cid(9):persistence_key('protect_reset'):null():max_length(8):default(0),
        MultihostPresence = Col.IntegerField():cid(10):persistence_key('protect_reset'):null():max_length(32):default(1)
    }):create_if_not_exist(datas and datas['t_pcie_load_info'])
    obj.PCIeCardFlashChecker = db:Table('t_pcie_card_flash_checker', {
        GroupPosition = Col.TextField():cid(1):primary_key(),
        FaultStatus = Col.IntegerField():cid(2):persistence_key('protect_reset'):null():max_length(8),
        PCIeQuadrupleList = Col.JsonField():cid(3):null()
    }):create_if_not_exist(datas and datas['t_pcie_card_flash_checker'])
    obj.PCIeCardDisplayCustom = db:Table('t_pcie_display_custom', {
        QuadrupleId = Col.TextField():cid(1):primary_key():default('\'\''),
        CustomType = Col.TextField():cid(2):primary_key():default('\'\''),
        Enabled = Col.BooleandField():cid(3):null():default(false),
        CardType = Col.TextField():cid(4):null():default('\'NA\'')
    }, 'protect_power_off_retain'):create_if_not_exist(datas and datas['t_pcie_display_custom'])

    obj.tables = db.tables
    return setmetatable(obj, Pcie_deviceDBDatabase)
end

function Pcie_deviceDBDatabase:select(table, ...)
    return self.db:select(table, ...)
end

function Pcie_deviceDBDatabase:update(table, ...)
    return self.db:update(table, ...)
end

function Pcie_deviceDBDatabase:insert(table, ...)
    return self.db:insert(table, ...)
end

function Pcie_deviceDBDatabase:delete(table, ...)
    return self.db:delete(table, ...)
end

function Pcie_deviceDBDatabase:exec(...)
    return self.db:exec(...)
end

return Pcie_deviceDBDatabase.new
